﻿using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace Kaiser.InversionOfControl.InstanceProviders
{
    /// <summary>
    /// DI container accessor
    /// </summary>
    public class IocContainer
    {

        public static List<string> RegisterTypes = new List<string>();

        public bool isInit;

        #region Properties

        /// <summary>
        /// Get the current configured container
        /// </summary>
        /// <returns>Configured container</returns>
        public static IUnityContainer Current { get; set; }
        static IocContainer()
        {
            configureContainer();
        }

        #endregion

        #region Methods
        static void configureContainer()
        {
            /*
             * Add here the code configuration or the call to configure the container 
             * using the application configuration file
             */

            Current = new UnityContainer();

            //Current.AddNewExtension<Interception>();

            //-> Unit of Work and repositories
            //Current.RegisterType(typeof(BondStockUnitOfWork), new PerResolveLifetimeManager());

            #region 生命周期的管理模式

            #endregion


        }

        /// <summary>
        /// 注册类型
        /// </summary>
        /// <typeparam name="TFrom">父类或者接口</typeparam>
        /// <typeparam name="TTo">继承自父类或者接口的子类</typeparam>
        /// <param name="isIntercepitonEnable">是否需要方法拦截</param>
        /// <param name="behaviroType"></param>
        /// <param name="injectionMembers">构造函数参数</param>
        public static void RegisterType<TFrom, TTo>(bool isIntercepitonEnable = false, Type behaviroType = null, params InjectionMember[] injectionMembers) where TTo : TFrom
        {
            RegisterTypes.Add(typeof(TFrom).FullName);

            if (injectionMembers.Length == 0)
                Current.RegisterType<TFrom, TTo>();
            else
                Current.RegisterType<TFrom, TTo>(injectionMembers);

            //注册AOP
            if (!isIntercepitonEnable) return;
            registerInterception<TTo>(behaviroType);
        }

        ///  <summary>
        ///  注册类型
        ///  </summary>
        ///  <typeparam name="TFrom">父类或者接口</typeparam>
        ///  <typeparam name="TTo">继承自父类或者接口的子类</typeparam>
        ///  <param name="isIntercepitonEnable">是否需要方法拦截</param>
        ///  <param name="lifetimeManager">生命周期</param>
        /// Unity内置了6种生存期管理模型，其中有2种即负责对象实例的创建也负责对象实例的销毁（Disposing）。
        /// TransientLifetimeManager - 为每次请求生成新的类型对象实例。 (默认行为)
        /// ContainerControlledLifetimeManager - 实现Singleton对象实例。当容器被Disposed后，对象实例也被Disposed。
        /// HierarchicalifetimeManager - 实现Singleton对象实例。但子容器并不共享父容器实例，而是创建针对字容器的Singleton对象实例。当容器被Disposed后，对象实例也被Disposed。
        /// ExternallyControlledLifetimeManager - 实现Singleton对象实例，但容器仅持有该对象的弱引用（WeakReference），所以该对象的生存期由外部引用控制。
        /// PerThreadLifetimeManager - 为每个线程生成Singleton的对象实例，通过ThreadStatic实现。
        /// PerResolveLifetimeManager - 实现与TransientLifetimeManager类似的行为，为每次请求生成新的类型对象实例。不同之处在于对象实例在BuildUp过程中是可被重用的。
        /// <param name="behaviroType"></param>
        /// <param name="injectionMembers">构造函数参数</param>
        public static void RegisterType<TFrom, TTo>(LifetimeManager lifetimeManager, bool isIntercepitonEnable = false, Type behaviroType = null, params InjectionMember[] injectionMembers) where TTo : TFrom
        {
            RegisterTypes.Add(typeof(TFrom).FullName);
            Current.RegisterType<TFrom, TTo>(lifetimeManager, injectionMembers);
            //注册AOP
            if (!isIntercepitonEnable) return;
            registerInterception<TTo>(behaviroType);
        }


        private static void registerInterception<TTo>(Type behaviroType)
        {
            registerInterception(typeof(TTo), behaviroType);
        }

        private static void registerInterception(Type type, Type behaviroType = null)
        {

            if (behaviroType == null)
            {
                return;
            }
            Current.RegisterType(type, new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior(behaviroType));

            Current.AddNewExtension<Interception>().Configure<Interception>().SetInterceptorFor(type, new VirtualMethodInterceptor());
        }

        public static void RegisterType(Type source, bool isIntercepitonEnable = false, Type behaviroType = null)
        {
            RegisterTypes.Add(source.FullName);
            Current.RegisterType(source);
            if (!isIntercepitonEnable) return;
            registerInterception(source, behaviroType);
        }

        public static object Resolve(Type source)
        {
            return Current.Resolve(source);
        }

        public static T Resolve<T>()
        {
            return Current.Resolve<T>();
        }

        public static bool HasRegistered(string typeFullName)
        {
            return RegisterTypes.Contains(typeFullName);
        }
        #endregion

    }
}